package com.powernode.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.clients.ProductClient;
import com.powernode.domain.Basket;
import com.powernode.domain.Sku;
import com.powernode.mapper.BasketMapper;
import com.powernode.model.CartItem;
import com.powernode.model.ShopCart;
import com.powernode.service.BasketService;
import com.powernode.vo.CartTotalAmount;
import com.powernode.vo.CartVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class BasketServiceImpl extends ServiceImpl<BasketMapper, Basket> implements BasketService{
    @Autowired
    private BasketMapper basketMapper;

    @Autowired
    private ProductClient productClient;

    @Override
    public Integer loadCartCount() {
        List<Object> objects = basketMapper.selectObjs(new QueryWrapper<Basket>()
                .select("IFNULL(SUM(basket_count),0)")
        );
        Object o = objects.get(0);
        return Integer.parseInt(o.toString());
    }

    /**
     * 最终购物车商品条目中的数据来自两张表：购物车表和sku表
     *
     *
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public CartVo selectUserBasketInfo(String userId) {
        // 1. 最终返回的就是cartVo
        CartVo cartVo = new CartVo();

        // 2. 根据用户标识查询购物车列表
        List<Basket> baskets = basketMapper.selectList(new LambdaQueryWrapper<Basket>()
                .eq(Basket::getUserId, userId)
        );

        // 3. 判断购物车是否有值
        if (CollectionUtil.isEmpty(baskets) || baskets.size() == 0) {
            return cartVo;
        }

        // 4. 如果购物车有值
        // 5. 从购物车集合获取商品sku集合
        List<Long> skuIds = baskets.stream().map(item -> item.getSkuId()).collect(Collectors.toList());

        // 6. 根据skuIds查询商品sku对象集合（远程调用）
        List<Sku> skuList = productClient.getSkuListBySkuIds(skuIds);
        if (CollectionUtil.isEmpty(skuList) || skuList.size() == 0) {
            throw new RuntimeException("服务器开小差了");
        }

        List<ShopCart> shopCartList = new ArrayList<>();

        HashSet<Long> shopIds = new HashSet<>();
        baskets.forEach(item -> {
            shopIds.add(item.getShopId());
        });

        shopIds.forEach(item -> {
            ShopCart shopCart = new ShopCart();
            shopCart.setShopId(item);
            shopCart.setShopCartItems(new ArrayList<CartItem>());
            shopCartList.add(shopCart);

        });

        // 7. 循环购物车列表
        baskets.forEach(basket -> {

            // 过滤当前条目的sku
            Sku sku = skuList.stream()
                    .filter(item -> item.getSkuId().equals(basket.getSkuId()))
                    .collect(Collectors.toList()).get(0);

            // 创建一个店铺对象
            CartItem cartItem = CartItem.builder()
                    .basketId(basket.getBasketId())
                    .basketCount(basket.getBasketCount())
                    .prodId(basket.getProdId())
                    .skuId(basket.getSkuId())
                    .prodName(sku.getProdName())
                    .skuName(sku.getSkuName())
                    .pic(sku.getPic())
                    .price(sku.getPrice()).build();

            // 获取一个店铺
            ShopCart shop = shopCartList
                    .stream()
                    .filter(item -> item.getShopId().equals(basket.getShopId()))
                    .collect(Collectors.toList()).get(0);

            shop.getShopCartItems().add(cartItem);
        });

        cartVo.setShopCarts(shopCartList);

        return cartVo;
    }

    @Override
    public CartTotalAmount selectUserCartTotalAmount(String userId, List<Long> basketIds) {

        CartTotalAmount cartTotalAmount = new CartTotalAmount();

        if (CollectionUtil.isEmpty(basketIds) || basketIds.size() == 0) {
            return cartTotalAmount;
        }

        // 1. 查询到basket对象
        List<Basket> baskets = basketMapper.selectList(new LambdaQueryWrapper<Basket>()
                .eq(Basket::getUserId, userId)
                .in(Basket::getBasketId, basketIds)
        );

        if (CollectionUtil.isEmpty(baskets) || baskets.size() == 0) {
            return cartTotalAmount;
        }

        // 2. 获取到skuids
        List<Long> skuIds = baskets.stream().map(item -> item.getSkuId()).collect(Collectors.toList());

        // 3. 远程调用获取sku对象
        List<Sku> skuList = productClient.getSkuListBySkuIds(skuIds);

        // 4. 循环baskets获取总金额
        List<BigDecimal> bigDecimalList = new ArrayList<>();

        baskets.forEach(item -> {
            Sku matchSku = skuList.stream()
                    .filter(sku -> item.getSkuId()
                            .equals(sku.getSkuId()))
                    .collect(Collectors.toList()).get(0);

            BigDecimal price = new BigDecimal(item.getBasketCount()).multiply(matchSku.getPrice());
            bigDecimalList.add(price);
        });

        // 5. 获取总金额
        BigDecimal totalMoney = bigDecimalList.stream().reduce(new BigDecimal(0), BigDecimal::add);
        cartTotalAmount.setTotalMoney(totalMoney);
        cartTotalAmount.setFinalMoney(totalMoney);

        if (totalMoney.compareTo(new BigDecimal(99)) == -1) {
            cartTotalAmount.setTransMoney(new BigDecimal(6));
            cartTotalAmount.setFinalMoney(totalMoney.add(new BigDecimal(6)));
        }

        return cartTotalAmount;
    }

    /**
     * 添加或增加购物车中商品的数量
     * @param basket
     */
    @Override
    public void addAndModifyBasketProdCount(Basket basket) {
        // 1. 查询是否存在与购物车
        Basket bk = basketMapper.selectOne(new LambdaQueryWrapper<Basket>()
                .eq(Basket::getUserId, basket.getUserId())
                .eq(Basket::getSkuId, basket.getSkuId())
        );

        // 2. 如果为空则添加一条记录到数据库
        if (ObjectUtil.isNull(bk)) {
            basket.setBasketDate(new Date());
            basket.setShopId(1L);
            basketMapper.insert(basket);
            return;
        }

        // 3. 如果不为空则
        int finalCount = bk.getBasketCount() + basket.getBasketCount();
        bk.setBasketCount(finalCount);
        bk.setBasketDate(new Date());
        basketMapper.updateById(bk);
    }
}
